<?php


namespace App\Services\Member\Services;

use App\Businesses\BusinessState;
use App\Constant\ApiV2Constant;
use App\Events\UserRegisterEvent;
use App\Events\UserVideoWatchedEvent;
use App\Exceptions\ServiceException;
use App\Services\Base\Interfaces\ConfigServiceInterface;
use App\Services\Base\Services\ConfigService;
use App\Services\Business\Models\Conquer;
use App\Services\Business\Models\Plan;
use App\Services\Business\Models\UserConquer;
use App\Services\Business\Models\WeightFragment;
use App\Services\Business\Models\Favorite;
use App\Services\Business\Models\Follow;
use App\Services\Business\Models\ThumbsUp;

use App\Services\Member\Interfaces\UserInviteBalanceServiceInterface;
use App\Services\Member\Interfaces\UserServiceInterface;
use App\Services\Member\Models\Activity;
use App\Services\Member\Models\FavoriteCategory;
use App\Services\Member\Models\User;
use App\Services\Member\Models\UserLoginRecord;
use App\Services\Member\Models\UserProfile;
use App\Services\Member\Models\UserRechargeBalance;
use App\Services\Member\Models\UserRedpacket;
use App\Services\Member\Models\UserRedpacketBalance;
use App\Services\Member\Models\UserRole;
use App\Services\Order\Models\TransferBalance;
use App\Services\Order\Models\UserRedeemCode;
use App\Services\Member\Models\Address;
use App\Services\Other\Models\UserPrize;
use Carbon\Carbon;
use Composer\Package\Dumper\ArrayDumper;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use App\Services\Business\Models\Run;
use App\Services\Business\Models\UserRedpacketRecord;
use Illuminate\Support\Facades\Log;
use App\Models\AdministratorRoleRelation;
use App\Services\Member\Models\Family;



class UserService implements UserServiceInterface
{
    /**
     * @var ConfigService
     */
    protected $configService;
    protected $businessState;

    public function __construct(ConfigServiceInterface $configService, BusinessState $businessState)
    {
        $this->configService = $configService;
        $this->businessState = $businessState;
    }

    /**
     * @return array
     */
    public function currentUser(): array
    {
        return $this->find(Auth::id(), ['role']);
    }

    /**
     * @param string $mobile
     *
     * @return array
     */
    public function findMobile(string $mobile): array
    {
        $user = User::whereMobile($mobile)->first();
        return $user ? $user->toArray() : [];
    }


    /**
     * @param string $mobile
     * @param string $password
     *
     * @return array
     */
    public function passwordLogin(string $mobile, string $password): array
    {
        $user = User::whereMobile($mobile)->first();
        if (!$user) {
            return [];
        }
        if (!Hash::check($password, $user->password)) {
            return [];
        }

        return $user->toArray();
    }

    /**
     * @param int $userId
     * @param string $oldPassword
     * @param string $newPassword
     *
     * @throws \Exception
     */
    public function resetPassword(int $userId, string $oldPassword, string $newPassword): void
    {
        $user = User::findOrFail($userId);
        if ($oldPassword && !Hash::check($oldPassword, $user->password)) {
            throw new ServiceException(__('原密码错误'));
        }
        $this->changePassword($user->id, $newPassword);
    }

    /**
     * 找回密码
     *
     * @param $mobile string 手机号
     * @param $password string 新密码
     */
    public function findPassword(string $mobile, string $password): void
    {
        $user = User::whereMobile($mobile)->firstOrFail();
        $this->changePassword($user->id, $password);
    }

    /**
     * @param int $userId
     * @param string $password
     */
    public function changePassword(int $userId, string $password): void
    {
        User::whereId($userId)->update([
            'password' => Hash::make($password),
            'is_password_set' => 1,
        ]);
    }

    /**
     * @param string $avatar
     * @param string $name
     * @return array
     * @throws \Exception
     */
    public function createWithoutMobile(string $avatar = '', string $name = ''): array
    {
        $user = User::create([
            'uuid' => 'zs' . time() . rand(1000, 9999),
            'avatar' => $avatar ?: $this->configService->getMemberDefaultAvatar(),
            'nick_name' => $name ?? Str::random(16),
            'mobile' => random_int(2, 9) . random_int(1000, 9999) . random_int(1000, 9999),
            'password' => Hash::make(Str::random(16)),
            'is_lock' => $this->configService->getMemberLockStatus(),
            'is_active' => $this->configService->getMemberActiveStatus(),
            'role_id' => 0,
            'is_set_nickname' => 0,
        ]);

        event(new UserRegisterEvent($user->id));

        return $user->toArray();
    }

    /**
     * @param string $mobile
     * @param string $password
     * @param string $nickname
     * @param string $avatar
     * @return array
     */
    public function createWithMobile(string $mobile, string $password, string $nickname, string $avatar = ''): array
    {
        $user = User::create([
            'uuid' => 'zs' . time() . rand(1000, 9999),
            'avatar' => $avatar ?: $this->configService->getMemberDefaultAvatar(),
            'nick_name' => $nickname ?: Str::random(12),
            'mobile' => $mobile,
            'password' => Hash::make($password ?: Str::random(10)),
            'is_lock' => $this->configService->getMemberLockStatus(),
            'is_active' => $this->configService->getMemberActiveStatus(),
            'role_id' => 0,
            'is_set_nickname' =>  0,
            'is_set_avatar' =>  0,
            'is_password_set' =>  0,
        ]);

        //所属平台
        event(new UserRegisterEvent($user->id));

        return $user->toArray();
    }

    /**
     * @param string $mobile
     * @param int $userId
     *
     * @throws ServiceException
     */
    public function bindMobile(string $mobile, int $userId): void
    {
        $user = User::query()->where('id', $userId)->first();

        if (!$this->businessState->isNeedBindMobile($user->toArray())) {
            throw new ServiceException(__('该账号已绑定手机号'));
        }

        if (User::query()->where('mobile', $mobile)->exists()) {
            throw new ServiceException(__('手机号已存在'));
        }

        $user->mobile = $mobile;
        $user->save();
    }

    /**
     * 更换手机号
     *
     * @param integer $userId
     * @param string $mobile
     * @return void
     */
    public function changeMobile(int $userId, string $mobile): void
    {
        $exists = $this->findMobile($mobile);
        if ($exists) {
            //todo  这里业务场景是用微信公众号登录 绑定手机号 之前用过过微信号登录有另外的账户，需要合并账户的处理
            throw new ServiceException(__('手机号已存在'));
        }
        $user = User::findOrFail($userId);
        $user->mobile = $mobile;
        $user->save();
    }

    /**
     * @param $userId
     * @param $avatar
     */
    public function updateAvatar(int $userId, string $avatar): void
    {
        User::query()->where('id', $userId)->update(['avatar' => $avatar, 'is_set_avatar' => 1]);
    }

    /**
     * @param $userId
     * @param $bgImage
     */
    public function updateBgImage(int $userId, string $bgImage): void
    {
        $profile = UserProfile::query()->where('user_id', $userId)->first();
        //删除
        $url = $profile['bg_image'];
        $url && Storage::disk('oss')->delete(substr($url, strrpos($url, "bg_image"), strlen($url) - strrpos($url, "bg_image")));
        UserProfile::query()->where('user_id', $userId)->update(['bg_image' => $bgImage]);
    }

    public function updateConquerBgImage(int $userId, $conquerId, string $bgImage): void
    {
        $userConquer = UserConquer::query()->where('user_id', $userId)->where('conquer_id', $conquerId)->first();
        //删除
        $url = $userConquer['cover'];
        $url && Storage::disk('oss')->delete(substr($url, strrpos($url, "conquer_bg_image"), strlen($url) - strrpos($url, "conquer_bg_image")));
        $userConquer->update(['cover' => $bgImage]);
    }


    public function updateBrief(int $userId, string $brief): void
    {
        User::query()->where('id', $userId)->update(['brief_introduce' => $brief]);
    }

    /**
     * @param int $userId
     * @param string $nickname
     * @throws ServiceException
     */
    public function updateNickname(int $userId, string $nickname): void
    {

        User::query()
            ->where('id', $userId)
            ->update([
                'nick_name' => $nickname,
                'is_set_nickname' => 1

            ]);
    }

    public function updateNicknameAndAvatar(int $userId, string $nickname, string $avatar): void
    {

        User::query()
            ->where('id', $userId)
            ->update([
                'nick_name' => $nickname,
                'avatar' => $avatar
            ]);
    }

    /**
     * @param array $ids
     * @param array $with
     *
     * @return array
     */
    public function getList(array $ids, array $with = []): array
    {
        return User::with($with)->select(['id', 'nick_name', 'uuid', 'avatar'])->whereIn('id', $ids)->get()->toArray();
    }


    /**
     * @param array $ids
     * @param array $with
     *
     * @return array
     */
    public function findMany(array $ids): array
    {
        return User::query()->whereIn('id', $ids)->get()->toArray();
    }


    /**
     * @param int $id
     * @param array $with
     *
     * @return array
     */
    public function find(int $id, array $with = []): array
    {
        return User::with($with)->findOrFail($id)->toArray();
    }


    /**
     * @param int $page
     * @param int $pageSize
     *
     * @return array
     */
    public function messagePaginate(int $userId, int $page, int $pageSize): array
    {

        $query = User::find($userId)->notifications()->latest();

        $total = $query->count();
        $data = $query->forPage($page, $pageSize)->get();
        $list = $data->toArray();

        return compact('list', 'total');
    }

    /**
     * @param int $page
     * @param int $size
     *
     * @return array
     */
    public function chatMessagePaginate(int $userId, int $page, int $size): array
    {

        //todo 给别人发信息没有显示出来，只是把别人跟我信息的记录查询出来了，这里需要优化
        $messages = ChatRoom::whereIn('id', function ($query) use ($userId) {
            $query->select(DB::raw('MAX(id)'))->from('user_chat_room_message')
                ->where('to_id', $userId)
                ->groupBy('user_id');
        })->with(['chatter:id,nick_name,avatar']);
        $unreadMessageMap = ChatRoom::query()
            ->select('to_id', 'user_id', DB::raw('COUNT(*) as unread_count'))
            ->where('to_id', $userId)
            ->where('is_read', -1)
            ->groupBy('user_id', 'to_id')->get()->keyBy('user_id');

        $total = $messages->count();
        $list = $messages->latest()->forPage($page, $size)->get();

        return compact('list', 'total', 'unreadMessageMap');
    }


    public function getUserFavorites(array $filter): array
    {
        $keywords = $filter['keywords'];
        $userId = $filter['userId'];
        $categoryId = $filter['categoryId'];
        $page = $filter['page'];
        $size = $filter['size'];
        $type = $filter['type'];
        $query = Favorite::query()
            ->when($keywords, function ($query) use ($keywords) {
                $query->where('title', 'like', '%' . $keywords . '%');
            })
            ->when($type, function ($query) use ($type) {
                $query->where('favorable_type', 'App\Services\Business\Models\\' . ucfirst($type));
            })
            ->whereUserId($userId)
            ->when($categoryId, function ($query) use ($categoryId) {
                $ids = [$categoryId];
                $childrenIds = FavoriteCategory::query()
                    ->where('parent_id', $categoryId)
                    ->select(['id'])
                    ->get()
                    ->pluck('id')
                    ->toArray();
                $ids = array_merge($ids, $childrenIds);
                $query->whereIn('category_id', $ids);
            });
        $total = $query->count();
        $resourceIds = $query->forpage($page, $size)->pluck('favorable_id')->toArray();
        $model = 'App\Services\Business\Models\\' . ucfirst($type);
        $resource = new $model();
        // 查询对应的记录
        $list = $resource::query()
            ->whereIn('id', $resourceIds)
            ->get()->toArray();
        return compact('list', 'total');


    }


    public function getSubscribes(int $userId, int $page, int $size): array
    {
        $query = UserRole::query()->with(['shop', 'role'])->whereUserId($userId)->orderByDesc('created_at');
        $total = $query->count();
        $list = $query->get()->forPage($page, $size)->toArray();

        return compact('list', 'total');
    }

    public function getBuyPapers(int $userId, int $shopId, int $page, int $size): array
    {
        $query = UserPaper::query()->with(['paper'])
            ->whereUserId($userId)
            ->when($shopId, function ($query, $shopId) {
                return $query->whereCompanyId($shopId);
            })
            ->orderByDesc('created_at');
        $total = $query->count();
        $list = $query->get()->forPage($page, $size)->toArray();

        return compact('list', 'total');
    }


    public function getBuyAnthologies(int $userId, int $shopId, int $page, int $size): array
    {
        $query = UserAnthology::query()
            ->with(['anthology'])
            ->whereUserId($userId)
            ->when($shopId, function ($query, $shopId) {
                return $query->whereCompanyId($shopId);
            })
            ->orderByDesc('created_at');
        $total = $query->count();
        $list = $query->get()->forPage($page, $size)->toArray();

        return compact('list', 'total');
    }

    /**
     * @param int $page
     * @param int $pageSize
     *
     * @return array
     */
    public function getBuyGroups(int $userId, int $shopId, int $page, int $pageSize): array
    {
        $query = UserGroup::query()->with(['group'])
            ->whereUserId($userId)
            ->when($shopId, function ($query, $shopId) {
                return $query->whereCompanyId($shopId);
            })
            ->orderByDesc('created_at');

        $total = $query->count();
        $list = $query->forPage($page, $pageSize)->get()->toArray();

        return compact('list', 'total');
    }


    public function getUserFavoriteCategory(): array
    {
        return FavoriteCategory::query()
            ->select('id', 'name', 'favorite_count')
            ->where('user_id', Auth::id())
            ->orderByDesc('created_at')->get()->toArray();

    }

    public function getUserAddresses(): array
    {
        return Address::query()
            ->where('user_id', Auth::id())
            ->orderByDesc('is_default')->get()->toArray();

    }


    public function getUserRechargeBlance(int $userId, $page, $size): array
    {
        $query = UserRechargeBalance::query()
            ->where('user_id', $userId)
            ->orderByDesc('created_at');
        $recharge = round((clone $query)->where('balance', '>', 0)->sum('balance'),2);
        $expense =round((clone $query)->where('balance', '<', 0)->sum('balance'),2);
        $list = $query->forPage($page, $size)->get()->toArray();
        $total = $query->count();
        return compact('list', 'total','recharge','expense');
    }


    /**
     * 获取计划
     * @param int $userId
     * @param $year
     * @param $status
     * @param $page
     * @param $size
     * @return array
     */
    public function getUserPlans(int $userId, $year, $status, $page, $size): array
    {
        $query = Plan::query()
            ->when($userId, function ($query) use ($userId) {
                $query->where('user_id', $userId);
            })
            ->where('status',$status)
            ->whereYear('created_at',$year)
            ->orderByDesc('created_at');
        $list = $query->forPage($page, $size)->get()->toArray();
        $total = $query->count();
        return compact('list', 'total');
    }




    public function getUserConquers(int $userId, $page, $size): array
    {
        $ids = UserConquer::query()->where('user_id',$userId)->pluck('conquer_id')->toArray();
        $query = Conquer::query()
            ->when($ids, function ($query) use ($ids) {
                $query->whereIn('id', $ids);
            })
            ->orderByDesc('created_at');
        $list = $query->forPage($page, $size)->get()->toArray();
        $total = $query->count();
        return compact('list', 'total');
    }

    public function getUserRuns(int $userId, $page, $size): array
    {
        $query = Run::query()
            ->with(['user','images', 'videos','redpacketRecord','redpacketRecord.sender:id,nick_name,avatar'])
            ->where('user_id',$userId)
            ->orderByDesc('created_at');
        $list = $query->forPage($page, $size)->get()->toArray();
        $total = $query->count();
        return compact('list', 'total');
    }

    public function getBlessingBalance(int $userId, int $receiverId, $page, $size): array
    {
        $query = UserRedpacketBalance::query()
            ->with(['receiver:id,nick_name,avatar'])
            ->when($receiverId, function ($query) use ($receiverId) {
                $query->where('receiver_id', $receiverId);
            })
            ->where('user_id', $userId)
            ->orderByDesc('created_at');
        $list = $query->forPage($page, $size)->get()->toArray();
        $total = $query->count();
        return compact('list', 'total');
    }
    public function getBlessingRecord(int $userId,Array $month,int $receiverId, $page, $size): array
    {
        $query = UserRedpacketRecord::query()
            ->with(['receiver:id,nick_name,avatar'])
            ->when($receiverId, function ($query) use ($receiverId) {
                $query->where('receiver_id', $receiverId);
            })
            ->whereBetween('created_at', [$month['start_at'], $month['end_at']])
            ->where('sender_id', $userId)
            ->orderByDesc('created_at');

// 获取汇总字段的总和和分页数据
        $totalAmount = round($query->sum('red_packet'),2);
        $total  = $query->count();
        $list = $query->forPage($page, $size)->get()->toArray();

// 返回结果

        return compact('list', 'total','totalAmount');
    }




    public function getUserConquerRecords(int $userId, $page, $size): array
    {
        $query = UserConquer::query()
            ->with(['conquer'])
            ->when($userId, function ($query) use ($userId) {
                $query->where('user_id', $userId);
            })
            ->orderByDesc('created_at');
        $list = $query->forPage($page, $size)->get()->toArray();
        $total = $query->count();
        return compact('list', 'total');
    }


    public function getUserWeightFragmentByConquer(int $userId, int $conquerId, $page, $size): array
    {
        $query = WeightFragment::query()
            ->with(['images', 'videos'])
            ->when($userId, function ($query) use ($userId) {
                $query->where('user_id', $userId);
            })
            ->when($conquerId, function ($query) use ($conquerId) {
                $query->where('conquer_id', $conquerId);
            })
            ->orderByDesc('created_at');
        $list = $query->forPage($page, $size)->get()->toArray();
        $total = $query->count();
        return compact('list', 'total');
    }

    public function getUserWeightFragmentTrendByConquer(int $userId, int $conquerId, $days)
    {
        return WeightFragment::query()
            ->select('weight', 'created_at')
            ->where('user_id', $userId)
            ->where('conquer_id', $conquerId)
            ->where('created_at', '>', now()->subDays($days))
            ->orderBy('created_at', 'asc')
            ->get()->map(function ($item) {
                $item->date = $item->created_at->format('m/d');
                return $item;
            })->keyBy('date')->toArray();


    }


    /**
     * @param int $userId
     * @param int $conquerId
     * @param $date
     * @return array
     */

    public function getUserImageByConquerAndDate(int $userId, int $conquerId, $date, $page, $size)
    {
        $query = WeightFragment::query()
            ->with(['images', 'videos'])
            ->when($userId, function ($query) use ($userId) {
                $query->where('user_id', $userId);
            })
            ->when($conquerId, function ($query) use ($conquerId) {
                $query->where('conquer_id', $conquerId);
            })
            ->when($date, function ($query) use ($date) {
                $query->whereDate('created_at', $date);
            });
        $list = $query->forPage($page, $size)->get()->toArray();
        $total = $query->count();
        return compact('list', 'total');
    }


    public function getUserDistricts(int $userId, $page, $size)
    {

        $query = UserLocation::query()
            ->with(['district'])
            ->when($userId, function ($query) use ($userId) {
                $query->where('user_id', $userId);
            })
            ->orderByDesc('created_at');
        $list = $query->forPage($page, $size)->get()->toArray();
        $total = $query->count();
        return compact('list', 'total');

    }


    public function getUserPrizes(int $userId, int $page, int $size): array
    {
        $query = UserPrize::query()
            ->whereUserId($userId)
            ->orderByDesc('created_at');

        $total = $query->count();
        $list = $query->forPage($page, $size)->get()->toArray();

        return compact('list', 'total');
    }

    public function getUserNotes(int $userId, string $keywords, int $videoId, int $size): array
    {

        $notes = Note::query()
            ->with(['video'])
            ->when($videoId, function ($query) use ($videoId) {
                $query->where('video_id', $videoId);
            })
            ->when($keywords, function ($query) use ($keywords) {
                return $query->where('title', 'like', '%' . $keywords . '%');
            })
            ->whereUserId($userId)
            ->orderByDesc('created_at')
            ->paginate($size);

        return compact('notes');

    }


    public function updateAccount($userId, $charge)
    {

        $user = User::query()->where('id', $userId)->first();
        $originAccount = $user['account'];
        User::query()->where('id', $userId)->update(['account' =>$originAccount + $charge]);
        UserRechargeBalance::create(['user_id' => $userId, 'balance' => $charge, 'remain' =>$originAccount + $charge, 'title' => '余额充值']);

    }


    public function tansferIn($userId, $balance)
    {

        TransferBalance::create(['user_id'=>$userId,'balance'=>$balance]);

    }

    public  function  redpacketBalance($senderId,$receiverId)
    {


        $redpacket = UserRedpacket::query()->where('user_id', $senderId)->where('receiver_id', $receiverId)->first();

        $rewardString = $redpacket->reward_value;
        $rewardArray = explode("|", $rewardString);
        $selectedRedpacket = array_shift($rewardArray);
        $remainingRewards = implode("|", array_values($rewardArray));
        $redpacket->reward_value = $remainingRewards;
        $redpacket->parts = $redpacket->parts - 1;
        $redpacket->total = $redpacket->total - $selectedRedpacket;
        $redpacket->claim_count = $redpacket->claim_count + 1;
        $redpacket->claim_total = $redpacket->claim_total + $selectedRedpacket;
        $redpacket->save();
    }


    /**
     * @param int $userId
     * @param int $videoId
     * @return bool
     */


    /**
     * @param int $userId
     * @param int $roleId
     * @param int $shopId
     * @param string $expiredAt
     */
    public function changeRole(int $userId, int $roleId, int $shopId, string $expiredAt, int $isForeverMembership): void
    {
        $record = UserRole::query()->where('user_id', $userId)->where('role_id', $roleId)->first();
        if (!$record) {
            UserRole::create([
                'user_id' => $userId,
                'company_id' => $shopId,
                'role_id' => $roleId,
                'is_forever_membership' => $isForeverMembership,
                'expired_at' => Carbon::parse($expiredAt),
                'created_at' => now(),
                'updated_at' => now(),
            ]);
        } else {
            UserRole::whereId($record->id)->update([
                'role_id' => $roleId,
                'expired_at' => Carbon::parse($expiredAt),
                'is_forever_membership' => $isForeverMembership,
                'updated_at' => now(),
            ]);
        }

    }


    /**
     * @param int $page
     * @param int $size
     * @return array
     */
    public function inviteUsers(int $page, int $size): array
    {
        $query = User::whereInviteUserId(Auth::id())->select(['id', 'nick_name', 'avatar', 'invite_user_id', 'uuid'])->orderByDesc('id');
        $total = $query->count();
        $list = $query->forPage($page, $size)->get()->toArray();

        return compact('list', 'total');
    }

    /**
     * @param int $id
     * @param $userId
     * @param int $reward
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function updateInviteUserId(int $id, $userId, $reward = 0): void
    {
        $inviteConfig = $this->configService->getMemberInviteConfig();
        $expiredDays = $inviteConfig['effective_days'] ?? 0;
        User::whereId($id)->update([
            'invite_user_id' => $userId,
            'invite_user_expired_at' => $expiredDays ? Carbon::now()->addDays($expiredDays) : null,
        ]);
        /**
         * @var $userInviteBalanceService UserInviteBalanceService
         */
        $userInviteBalanceService = app()->make(UserInviteBalanceServiceInterface::class);
        $userInviteBalanceService->createInvite($userId, $reward);
    }


    /**
     * @param int $userId
     * @return int
     */
    public function getUserCourseCount(int $userId): int
    {
        return (int)UserCourse::query()->where('user_id', $userId)->count();
    }


    /**
     * @param int $userId
     * @param int $inc
     */
    public function inviteBalanceInc(int $userId, int $inc): void
    {
        User::find($userId)->increment('invite_balance', $inc);
    }

    /**
     * @param int $userId
     * @param string $id
     */
    public function notificationMarkAsRead(int $userId, string $id): void
    {
        $notification = User::find($userId)->notifications()->whereId($id)->first();
        $notification && $notification->markAsRead();
    }

    /**
     * @param int $userId
     */
    public function notificationMarkAllAsRead(int $userId): void
    {
        User::find($userId)->unreadNotifications->markAsRead();
    }

    /**
     * 未读消息数量
     *
     * @param integer $userId
     * @return int
     */
    public function unreadNotificationCount(int $userId): int
    {
        return (int)User::find($userId)->unreadNotifications->count();
    }

    /**
     * 未读动态数量
     *
     * @param integer $userId
     * @return int
     */
    public function unreadFeedCount(int $userId): int
    {
        $user = User::find($userId);
        $followingids = $user->followings()->pluck('following_id')->toArray();
        return (int)Activity::query()->whereIn('user_id', $followingids)->whereBetween('created_at', [$user['last_follow_updated_at'], Carbon::now()])->count();
    }


    /**
     * @param int $userId
     * @param int $resourseId
     * @return int
     */


    public function isClaimedCode(int $userId, int $codeId): bool
    {
        return UserRedeemCode::whereRedeemCodeId($codeId)->whereUserId($userId)->exists();
    }

    public function isFollowed(int $followerId, int $followingId): bool
    {
        return Follow::whereFollowerId($followerId)->whereFollowingId($followingId)->exists();
    }


    public function isAttended(int $conquerId, int $userId): bool
    {
        return UserConquer::whereConquerId($conquerId)->whereUserId($userId)->exists();
    }

    public function isPublishedToday(int $conquerId, int $userId): bool
    {
        return WeightFragment::whereConquerId($conquerId)->whereUserId($userId)->whereDate('created_at', now()->toDateString())->exists();

    }


    public function isFavorited(int $userId, int $favorableId, string $favorableType): bool
    {
        return Favorite::whereUserId($userId)->whereFavorableId($favorableId)->whereFavorableType($favorableType)->exists();
    }


    public function isThumbsuped(int $userId, int $thumbsableId, string $thumbsableType): bool
    {
        return ThumbsUp::whereUserId($userId)->whereThumbsupableId($thumbsableId)->whereThumbsupableType($thumbsableType)->exists();
    }



    /**
     * 获取用户视频观看记录
     * @param int $userId
     * @param int $courseId
     * @return array
     */
    public function getUserVideoWatchRecords(int $userId, int $courseId): array
    {
        $records = UserVideoWatchRecord::query()->where('user_id', $userId)->where('course_id', $courseId)->get();
        return $records->toArray();
    }

    /**
     * 获取课程的最新一条观看记录
     * @param int $userId
     * @param int $courseId
     * @return array
     */
    public function getLatestRecord(int $userId, int $courseId): array
    {
        $record = UserVideoWatchRecord::query()->where('user_id', $userId)->where('course_id', $courseId)->orderByDesc('updated_at')->first();
        return $record ? $record->toArray() : [];
    }

    /**
     * @param int $id
     */
    public function setUsedPromoCode(int $id): void
    {
        User::query()->where('id', $id)->update(['is_used_promo_code' => 1]);
    }

    /**
     * @param int $id
     * @param string $ip
     */
    public function setRegisterIp(int $id, string $ip): void
    {
        User::query()->where('id', $id)->update(['register_ip' => $ip]);
    }

    /**
     * @param int $id
     * @param array $area
     */
    public function setRegisterArea(int $id, array $area): void
    {
        $area && User::query()->where('id', $id)->update(['register_province' => $area['province'] ?? '', 'register_city' => $area['city'] ?? '']);
    }

    /**
     * 重置会员过期用户
     *
     * @return int
     */
    public function resetRoleExpiredUsers(): int
    {
        return User::query()
            ->where('expired_at', '<=', Carbon::now())
            ->update(['role_id' => 0, 'expired_at' => null]);
    }

    /**
     * 用户登录记录
     *
     * @param int $userId
     * @param string $platform
     * @param string $ip
     * @param string $at
     */
    public function createLoginRecord(int $userId, string $platform, string $ip, string $at): void
    {
        $record = UserLoginRecord::create([
            'user_id' => $userId,
            'ip' => $ip,
            'area' => '',
            'platform' => $platform,
            'at' => $at,
        ]);

        User::query()->where('id', $userId)->update(['last_login_id' => $record->id]);
    }

    /**
     * @param int $userId
     * @param string $platform
     * @return array
     */
    public function findUserLastLoginRecord(int $userId, string $platform): array
    {
        $record = UserLoginRecord::query()
            ->where('user_id', $userId)
            ->when($platform, function ($query) use ($platform) {
                $query->where('platform', $platform);
            })
            ->orderByDesc('id')
            ->first();
        return $record ? $record->toArray() : [];
    }

    /**
     * 用户视频观看时间统计
     * @param int $userId
     * @param int $seconds
     */


    /**
     * @param int $userId
     * @return array
     */
    public function getProfile(int $userId): array
    {
        $profile = UserProfile::query()->where('user_id', $userId)->first();
        return $profile ? $profile->toArray() : [];
    }

    /**
     * @param int $userId
     * @param array $profileData
     */
    public function saveProfile(int $userId, array $profileData): void
    {
        $updateData = [];
        foreach (UserProfile::EDIT_COLUMNS as $column) {
            if (!isset($profileData[$column])) {
                continue;
            }
            if ($profileData[$column] !== null) {
                $updateData[$column] = $profileData[$column];
            }
        }

        $profile = UserProfile::query()->where('user_id', $userId)->first();
        if ($profile) {
            $profile->fill($updateData)->save();
        } else {
            $updateData['user_id'] = $userId;
            UserProfile::create($updateData);
        }
    }

    public function createPorfile(int $userId): void
    {

        $updateData['user_id'] = $userId;
        UserProfile::create($updateData);

    }




    /**
     * @param int $userId
     * @return int
     */
    public function isAdmin(int $userId): int
    {
        return (int)AdministratorRoleRelation::query()->where('user_id', $userId)->exists();
    }

    //关注人数
    public function followingCount(int $followerId): int
    {
        return (int)Follow::query()->where('follower_id', $followerId)->count();
    }

    //粉丝人数
    public function followerCount(int $followingId): int
    {
        return (int)Follow::query()->where('following_id', $followingId)->count();
    }

    public function followingIds(int $followerId): array
    {
        return (array)Follow::query()->where('follower_id', $followerId)->pluck('following_id')->toArray();
    }


    public function hasFamily(int $userId):int
    {
        return  (int)Family::query()->where('user_id', $userId)->exists();
    }


    public function isRole(int $userId): bool
    {
        $user = User::query()->find($userId);
        if (!$user['role_id'] || !$user['expired_at']) {
            return false;
        }
        if (Carbon::now()->gt($user['expired_at'])) {
            return false;
        }
        return true;

    }




    public function getActivities($id, $page, $size)
    {

        $query = Activity::query()->where('user_id', $id)->orderBy('activity_type');
        $activities = (clone $query)->forPage($page, $size)->get();
        $groups = $activities->groupBy('activity_type')->map(function ($group) {
            $activityIds = $group->pluck('activity_id')->implode(',');
            return [
                'activity_type' => $group->first()->activity_type,
                'activity_ids' => $activityIds,
            ];
        })
            ->values();


        $list = [];
// 遍历每个分组，根据 resource_id 查询对应的记录，并按照创建时间排序
        foreach ($groups as $group) {
            // 获取分组中的 resource_id，转换为数组形式
            $ids = explode(',', $group['activity_ids']);

            // 根据 activity_type 加载对应的模型关联
            $model = 'App\Services\Business\Models\\' . ucfirst($group['activity_type']);

            $resource = new $model();
            // 查询对应的记录
            $records = $resource::query()
                ->with(ApiV2Constant::MODEL_ACTIVITY_WITH_FIELD[$group['activity_type']])
                ->select(ApiV2Constant::MODEL_ACTIVITY_FIELD[$group['activity_type']])
                ->addSelect([DB::raw("'{$group['activity_type']}' AS type")])
                ->whereIn('id', $ids)
                ->orderBy('created_at', 'desc')
                ->get()
                ->toArray();
            $list = array_merge($list, $records);
        }
        $total = $query->count();
        return compact('list', 'total');

    }


    public function findRole(int $userId, int $roleId)
    {
        $role = UserRole::query()->where('role_id', $roleId)->where('user_id', $userId)->first();

        return $role ? $role->toArray() : [];

    }




}
